package cn.bonoon.kernel.bytecode;

import org.springframework.context.ApplicationContext;

import cn.bonoon.kernel.annotations.ReadModel;
import cn.bonoon.kernel.annotations.Transform;
import cn.bonoon.kernel.bytecode.asm.ASMConfigBuilder;
import cn.bonoon.kernel.bytecode.asm.ASMQueryBuilder;
import cn.bonoon.kernel.bytecode.asm.ASMReaderBuilder;
import cn.bonoon.kernel.bytecode.asm.ASMWriterBuilder;
import cn.bonoon.kernel.descriptors.DescriptorFactory;
import cn.bonoon.kernel.descriptors.EntityDescriptor;
import cn.bonoon.kernel.descriptors.ObjectDescriptor;

public class BytecodeFactory {
	
	private static final String DEFAULT_INIT_READER = "initReader";
	
	public static EntityReader reader(ApplicationContext applicationContext, Class<?> targetClass, EntityDescriptor entityDescriptor) throws Exception{
		return reader(applicationContext, DescriptorFactory.objectDescriptor(targetClass), entityDescriptor);
	}
	
	public static EntityReader reader(ApplicationContext applicationContext, ObjectDescriptor objectDescriptor, EntityDescriptor entityDescriptor) throws Exception{
		Transform transform = objectDescriptor.getAnnotation(Transform.class);
		String initReader;
		ReadModel read;
		if(null == transform){
			initReader = DEFAULT_INIT_READER;
			read = ReadModel.OPTIMIZE;
		}else{
			read = transform.read();
			if(read == ReadModel.NONE) throw new RuntimeException("只写模式，不能从数据库实体里读值！");
			initReader = transform.initReader();
		}
		return new ASMReaderBuilder(read, initReader, applicationContext, objectDescriptor, entityDescriptor).build();
	}
	
	public static EntityWriter writer(ApplicationContext applicationContext, Class<?> writeClass, EntityDescriptor entityDescriptor) throws Exception{
		ObjectDescriptor objectDescriptor = DescriptorFactory.objectDescriptor(writeClass);
		return new ASMWriterBuilder(objectDescriptor.getAnnotation(Transform.class), applicationContext, objectDescriptor, entityDescriptor).build();
	}
	
	public static QueryConverter query(ApplicationContext applicationContext, Class<?> queryClass, EntityDescriptor entityDescriptor) throws Exception{
		return new ASMQueryBuilder(applicationContext, entityDescriptor, DescriptorFactory.queryDescriptor(queryClass)).build();
	}
	
	public static ConfigConverter config(ApplicationContext applicationContext, Class<?> configClass) throws Exception{
		return new ASMConfigBuilder(applicationContext, DescriptorFactory.configDescriptorImpl(configClass)).build();
	}
}
